package com.chinasoft;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class MapData {
    public final static int WIDTH = 20;
    public static final int MAX_LEVEL = 50;
    private int[][] map = new int[WIDTH][WIDTH];
    private int level;
    private Man man;
    private List<Box> boxList = new ArrayList<Box>();

    public MapData() {
        level = 1;
        loadMap(level);
        man = getManFromMap();
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public boolean initLevel(int L) {// 加载新关卡的地图
        level = L;
        loadMap(level); // 加载新关卡的地图
        man = getManFromMap(); // 从新地图中获取角色对象
        return true;
    }
    private void initMap() {
		for (int i = 0; i < WIDTH; i++) {
			for (int j = 0; j < WIDTH; j++) {
				map[i][j] = 0;
			}
		}
	}


    public boolean nextLevel() {
        if (level == MAX_LEVEL) {
            return false;
        }
        level++;
        loadMap(level);
        man = getManFromMap();
        return true;
    }

    public int[][] getMap() {
        return map;
    }

    public void setMap(int[][] map) {
        this.map = map;
    }

    /**
     * 从地图中获取人的对象
     * <p>
     * 此方法遍历二维地图数组，寻找值为5的元素，该元素表示人的位置
     * 找到后，创建一个Man对象，设置其在地图上的位置，并返回这个对象
     * 如果遍历完整个地图没有找到人，则返回null
     *
     * @return Man对象，如果找到的话；否则返回null
     */
    public Man getManFromMap() {
        // 遍历地图的每一个位置
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < WIDTH; j++) {
                // 检查当前位置是否为人（用数字5表示）
                if (map[i][j] == 5) {
                    Man man = new Man();
                    man.setManX(j);
                    man.setManY(i);
                    // 将地图信息设置到人对象中
                    man.setMap(map);
                    man.setData(this);
                    // 找到了人
                    return man;
                }
            }
        }
        // 如果遍历完整个地图都没有找到人，返回null
        return null;
    }


    public Man getMan() {
        return man;
    }

    public void setMan(Man man) {
        this.man = man;
    }

    /**
     * 加载地图方法
     * 根据指定的关卡号加载对应地图文件
     *
     * @param level 关卡号，用于指定要加载的地图文件
     */
    public void loadMap(int level) {
        FileReader fr = null;
        BufferedReader reader = null;
        initMap();
        try {
            // 创建FileReader对象，用于读取地图文件
            fr = new FileReader(GamePanel.class.getResource("/maps/" + level + ".map").getPath());
            // 创建BufferedReader对象，用于提高读取效率
            reader = new BufferedReader(fr);
            String line = null;
            int i = 0;
            // 循环读取地图文件的每一行
            while ((line = reader.readLine()) != null) {
                // 将读取到的行转换为字符数组
                char[] arr = line.toCharArray();
                // 遍历字符数组，将字符转换为整数并存入地图数组
                for (int j = 0; j < arr.length; j++) {
                    map[i][j] = Integer.parseInt("" + arr[j]);
                }
                i++;
            }
        } catch (FileNotFoundException e) {
            // 捕获文件未找到异常
            e.printStackTrace();
        } catch (IOException e) {
            // 捕获IO异常
            e.printStackTrace();
        } finally {
            // 在finally块中关闭BufferedReader
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    // 捕获关闭流时可能发生的IO异常
                    e.printStackTrace();
                }
            }
        }
        initBoxes();
    }

    /**
     * 初始化盒子列表
     * 此方法用于根据地图数据创建和初始化盒子对象，并将它们添加到盒子列表中
     * 它会遍历地图的每个单元，当遇到特定值时（3或9），会创建相应的盒子对象，并设置其属性
     */
    private void initBoxes() {
        // 清空盒子列表，以便重新初始化
        boxList.clear();

        // 遍历地图的每个单元
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < WIDTH; j++) {
                // 当地图单元的值为3时，创建一个包含类型为2的盒子，并将其添加到列表中
                if (map[i][j] == 3) {
                    Box box = new Box(j, i, map);
                    box.setContains(2);
                    boxList.add(box);
                }
                // 当地图单元的值为9时，创建一个包含类型为4的盒子，并将其添加到列表中
                if (map[i][j] == 9) {
                    Box box = new Box(j, i, map);
                    box.setContains(4);
                    boxList.add(box);
                }
            }
        }
    }

    /**
     * 根据指定方向获取箱子
     * 此方法用于计算在给定方向上，角色位置的相邻箱子的位置，并返回该箱子
     *
     * @param d 方向枚举，表示相对于角色的目标方向
     * @return 返回指定位置的箱子对象，如果没有箱子则返回null
     */
    public Box getBoxByDirection(Direction d) {
        // 获取角色的当前位置坐标
        int x = man.getManX();
        int y = man.getManY();
        // 输出角色的当前位置信息
        System.out.println("man x = " + x + " y= " + y);

        // 根据给定的方向更新x或y坐标，以确定目标位置
        switch (d) {
            case Right:
                x++;
                break;
            case Left:
                x--;
                break;
            case Down:
                y++;
                break;
            case Up:
                y--;
                break;
            default:
                // 如果方向不明确，不进行坐标更新
                break;
        }

        // 调用findBox方法，根据更新后的坐标找到并返回箱子对象
        return findBox(x, y);
    }


    /**
     * 根据坐标查找对应的Box对象
     * 遍历一个Box对象列表，尝试匹配给定坐标的Box对象
     * 如果找到匹配的Box对象，则返回该对象；如果没有找到匹配的，则返回null
     *
     * @return 如果找到匹配的Box对象，则返回该对象；否则返回null
     */
    public Box findBox(int x, int y) {
        // 打印查找的坐标，用于调试
        System.out.println("x = " + x + " y= " + y);
        // showMymap();

        // 遍历boxList列表，尝试找到匹配给定坐标x和y的Box对象
        for (Box b : boxList) {
            // 如果当前Box对象匹配给定的坐标，则返回该Box对象
            if (b.match(x, y)) {
                return b;
            }
        }
        // 如果没有找到匹配的Box对象，返回null
        return null;
    }

    /**
     * 判断游戏是否胜利
     * <p>
     * 此方法通过检查所有盒子的状态来确定玩家是否获胜
     * 如果所有盒子的状态都是“Ok”，则表示玩家获胜；如果有一个盒子状态不是“Ok”，则玩家未获胜
     *
     * @return true 如果所有盒子状态都是“Ok”，表示玩家获胜；否则返回 false
     */
    public boolean isWin() {
        // 初始化胜利标志为 true，假设玩家已获胜
        boolean winFlag = true;

        // 遍历盒子列表，检查每个盒子的状态
        for (Box b : boxList) {
            // 如果发现盒子状态不是“Ok”，则设置胜利标志为 false，并立即返回
            if (b.isOk() == false) {
                winFlag = false;
                return winFlag;
            }
        }

        // 如果所有盒子状态都是“Ok”，则返回 true，表示玩家获胜
        return winFlag;
    }


}
